command! -n=0  -bar VXpush :call s:vxref_push()
command! -n=0  -bar VXpop :call s:vxref_pop()
command! -n=0  -bar VXstart :call s:vxref_start()
command! -n=1  -bar VXredraw :call s:vxref_redraw('<args>')



"function! s:start_vxref_server()
"  let ret = system("../sh/startserver.sh &")
"endfunction
"call s:start_vxref_server()


":let spid = getpid()
":let g:vx_wd = "/tmp/vxref." . spid

"-------------------------- start of common functions --------------------------------------

function! s:init_var(var, value)
  if !exists(a:var)
    exec 'let ' . a:var . ' = ' . "'" . a:value . "'"
    return 1
  endif
  return 0
endfunction

call s:init_var("g:vx_redraw", 0)
call s:init_var("g:vx_cmd_id", 1)
call s:init_var("g:spid", getpid())
call s:init_var("g:vx_wd", "/tmp/vxref." . g:spid)

function! s:vxref_redraw(val)
	exec 'let  g:vx_redraw = ' . "'" . a:val . "'"
endfunction

function! s:vxref_start()
	exec "silent !~/.vim/vxref/startserver.sh " . g:spid . " &> /dev/null &"
	autocmd VimLeave * :exec  "silent !~/.vim/vxref/cleanup.sh " . g:spid
	if g:vx_redraw
		silent exec ":redraw!"
	endif
endfunction

function! s:vxref_getcmdid()

  "get the id and increment the global command id
  let l:sid = eval(g:vx_cmd_id)
  let g:vx_cmd_id = eval(g:vx_cmd_id)+1
  if g:vx_cmd_id > 10
    let g:vx_cmd_id = 1
  endif

  return l:sid

endfunction

function! s:vxref_writelock(id)

  "write the cmd id to lock file
  let l:cmd = "silent !echo \"". a:id ."\" > " . g:vx_wd  .  "/vxref.lock;\n"
  silent exec l:cmd

  "read the lock file to make sure the correct id is written
  let @c = system( "awk 'NR==1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.lock"))
  let l:id = @c
  let l:id = eval("l:id")
  "stall while incorrect id is present
  while l:id != a:id
    let @c = system( "awk 'NR==1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.lock"))
    let l:id = @c
  endwhile

endfunction

function! s:vxref_readlock(id)

  "make sure that the id that is read is consistent
  let @c = system( "awk 'NR==1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.out"))
  let l:id = @c
  let l:id = eval("l:id")
  while l:id != a:id
    let @c = system( "awk 'NR==1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.out"))
    let l:id = @c
  endwhile

endfunction

function! s:vxref_doredraw()

  "clean up vim incase it gets screwed in the process
  if g:vx_redraw
    silent exec ":redraw!"
  endif

endfunction

"-------------------------- end of common functions --------------------------------------

function! s:vxref_pop()

  let l:sid =  s:vxref_getcmdid()
  call s:vxref_writelock(l:sid)

  "write the pop cmd to the xref server
  let l:cursor_bytepos=line2byte(line("."))+col(".")-2
  let l:current_file=expand("%:p")
  let l:cmd = "silent !echo -olcxpop > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  let l:cmd = l:cmd . "silent !echo \"".l:current_file."\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  let l:cmd = l:cmd . "silent !echo end-of-options > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  let l:cmd = l:cmd . "silent !echo \"\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  silent exec l:cmd

  call s:vxref_doredraw()
  call s:vxref_readlock(l:sid)

  "get command from file removing any trailing newlines and execute it
  let @a = system( "awk 'NR>1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.out") . " | tr -d '\n' ")
  let l:cmd = "". @a.""
  exec l:cmd

endfunction

function! s:vxref_push()

  let l:sid =  s:vxref_getcmdid()
  call s:vxref_writelock(l:sid)

  "write the push cmd to the xref server
  let l:cursor_bytepos=line2byte(line("."))+col(".")-2
  let l:current_file=expand("%:p")
  let l:cmd = "silent !echo -olcxpush > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  let l:cmd = l:cmd . "silent !echo -olcursor=".l:cursor_bytepos." > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  let l:cmd = l:cmd . "silent !echo \"".l:current_file."\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  let l:cmd = l:cmd . "silent !echo end-of-options > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  let l:cmd = l:cmd . "silent !echo \"\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  silent exec l:cmd

  call s:vxref_doredraw()
  call s:vxref_readlock(l:sid)

  "get command from file removing any trailing newlines and execute it
  let @a = system( "awk 'NR>1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.out") . " | tr -d '\n' ")
  let l:cmd = "". @a.""
  exec l:cmd

endfunction

function! VXref_compl(findstart, base)

  if a:findstart
    " following is taken straight from omni complete plugin
    " Locate the start of the item, including ".", "->" and "[...]".
    let line = getline('.')
    let start = col('.') - 1

    let lastword = -1
    while start > 0
        if line[start - 1] =~ '\w'
            let start -= 1
        elseif line[start - 1] =~ '\.'
            " Searching for dot '.'
            if lastword == -1
                let lastword = start
            endif
            let start -= 1
        elseif start > 1 && line[start - 2] == '-' && line[start - 1] == '>'
            " Searching for '->'
            if lastword == -1
                let lastword = start
            endif
            let start -= 2
        elseif start > 1 && line[start - 2] == ':' && line[start - 1] == ':'
            " Searching for '::' for namespaces and class
            if lastword == -1
                let lastword = start
            endif
            let start -= 2
        elseif line[start - 1] == ']'
            " Skip over [...].
            let n = 0
            let start -= 1
            while start > 0
                let start -= 1
                if line[start] == '['
                    if n == 0
                        break
                    endif
                    let n -= 1
                elseif line[start] == ']'  " nested []
                    let n += 1
                endif
            endwhile
        else
            break
        endif
    endwhile
    if lastword==-1
        " For completion on the current scope
        let lastword = start
    endif

    "setup xref cmd
    let l:sid =  s:vxref_getcmdid()
    call s:vxref_writelock(l:sid)

    "write the tmp preload file
    silent exec "w! " . g:vx_wd . "/vxref.preload"

    "send the complete cmd to the xref server
    let l:cursor_bytepos=line2byte(line("."))+col(".")-2
    let l:current_file=expand("%:p")
    let l:cmd = "silent !echo -olcxcomplet > " . g:vx_wd  .  "/vxref.fifo.in;\n"
    let l:cmd = l:cmd . "silent !echo -olcursor=".l:cursor_bytepos." > " . g:vx_wd  .  "/vxref.fifo.in;\n"
    let l:cmd = l:cmd . "silent !echo -preload ".l:current_file."  " . g:vx_wd . "/vxref.preload > " . g:vx_wd  .  "/vxref.fifo.in;\n"
    let l:cmd = l:cmd . "silent !echo \"".l:current_file."\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
    let l:cmd = l:cmd . "silent !echo end-of-options > " . g:vx_wd  .  "/vxref.fifo.in;\n"
    let l:cmd = l:cmd . "silent !echo \"\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
    silent exec l:cmd
    call s:vxref_doredraw()
    call s:vxref_readlock(l:sid)

    return lastword
  else
    let res = []
    " find months matching with "a:base"
    let @a = system( "awk 'NR>1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.out") )
    let l:cmd = "". @a.""
    silent exec l:cmd
   
    "let res = []
    "for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
    "  if m =~ '^' . a:base
    "    call add(res, { "word": m, "menu": "menustr"})
    "  endif
    "endfor
    return res
  endif

  "let l:sid =  s:vxref_getcmdid()
  "call s:vxref_writelock(l:sid)

  ""write the tmp preload file
  "silent exec "w! " . g:vx_wd . "/vxref.preload"

  "

  ""write the complete cmd to the xref server
  "let l:cursor_bytepos=line2byte(line("."))+col(".")-2
  "let l:current_file=expand("%:p")
  "let l:cmd = "silent !echo -olcxcomplet > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  "let l:cmd = l:cmd . "silent !echo -olcursor=".l:cursor_bytepos." > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  "let l:cmd = l:cmd . "silent !echo -preload ".l:current_file."  " . g:vx_wd . "/vxref.preload > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  "let l:cmd = l:cmd . "silent !echo \"".l:current_file."\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  "let l:cmd = l:cmd . "silent !echo end-of-options > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  "let l:cmd = l:cmd . "silent !echo \"\" > " . g:vx_wd  .  "/vxref.fifo.in;\n"
  "silent exec l:cmd

  "call s:vxref_doredraw()
  "call s:vxref_readlock(l:sid)

  "let @a = system( "awk 'NR>1{print;}' " . shellescape( "" . g:vx_wd  .  "/vxref.out") )
  "let l:cmd = "". @a.""
  "echo l:cmd

endfunction

set completefunc=VXref_compl
set completeopt=menu,menuone
